package org.tool.core.lang;

import cn.hutool.core.util.StrUtil;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.common.constant.MagicValue.UNDERSCORE;
import static org.common.constant.MagicValue.UNDERSCORE_CHAR;

/**
 * 字符串工具类
 *
 * @author 李坤
 * @date 2022/7/8 21:26
 */
public abstract class StringUtil extends StrUtil {

    public static final Pattern PATTERN = Pattern.compile("[<>\"'%()&+\\\\/”“]");

    /**
     * 将给定的对象转换为字符串；
     * 如果对象为空 - {@code null}，则返回空字符串 - {@code ""}
     *
     * @param target 待处理的对象
     *
     * @return 处理后的字符串
     */
    public static String toString(Object target) {
        return Objects.nonNull(target) ? target.toString() : EMPTY;
    }

    /**
     * 将给定的字符串从驼峰类型转为下划线类型
     *
     * @param param 待转换的字符串
     *
     * @return 转换后的字符串
     */
    public static String camelToUnderline(String param) {
        if (StrUtil.isNotBlank(param)) {
            final int length = param.length();
            final char[] chars = param.toCharArray();
            StringBuilder builder = new StringBuilder(length + length >> 1); // 扩充为原来的1.5倍

            // 将首字母转换为大写
            builder.append(Character.toUpperCase(chars[0]));
            // 循环处理其余字符
            for (int index = 1; index < length; index++) {
                final char aChar = chars[index];

                if (Character.isLowerCase(aChar)) {
                    builder.append(Character.toUpperCase(aChar));
                } else {
                    builder.append(UNDERSCORE);
                    builder.append(aChar);
                }
            }
            return builder.toString();
        }
        return param;
    }

    /**
     * 将给定的字符串从下划线类型转为驼峰类型
     *
     * @param param 待转换的字符串
     *
     * @return 转换后的字符串
     */
    public static String underlineToCamel(String param) {
        if (StrUtil.isNotBlank(param)) {
            boolean toUpperCase = false;
            final char[] chars = param.toCharArray();
            StringBuilder builder = new StringBuilder(param.length());

            // 循环处理其余字符
            for (final char aChar : chars) {
                if (aChar == UNDERSCORE_CHAR) {
                    toUpperCase = true;
                } else if (toUpperCase) {
                    builder.append(Character.isUpperCase(aChar) ? aChar : Character.toUpperCase(aChar));
                    toUpperCase = false;
                } else {
                    builder.append(Character.isLowerCase(aChar) ? aChar : Character.toLowerCase(aChar));
                }
            }
            return builder.toString();
        }
        return param;
    }

    /**
     * 去除字符串中具有攻击功能的特殊字符
     *
     * @param value 需要处理的字符
     *
     * @return 处理后的字符
     */
    public static String processInputString(String value) {
        if (Objects.nonNull(value) && !EMPTY.equals(value)) {
            Matcher matcher = PATTERN.matcher(value);
            if (matcher.find()) {
                return matcher.group();
            }

            Pattern scriptPattern = null;
            scriptPattern = Pattern.compile("<(no)?script[^>]*>.*?</(no)?script>", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
            scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
            scriptPattern = Pattern.compile("(javascript:|vbscript:|view-source:)*", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
            scriptPattern = Pattern.compile("<(\"[^\"]*\"|'[^']*'|[^'\">])*>", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
            scriptPattern = Pattern.compile("(window\\.location|window\\.|\\.location|document\\.cookie|document\\.|alert\\(.*?\\)|window\\.open\\()*", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
            scriptPattern = Pattern.compile("<+\\s*\\w*\\s*(oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondblclick|ondeactivate|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragstart|ondrop|onerror=|onerroupdate|onfilterchange|onfinish|onfocus|onfocusin|onfocusout|onhelp|onkeydown|onkeypress|onkeyup|onlayoutcomplete|onload|onlosecapture|onmousedown|onmouseenter|onmouseleave|onmousemove|onmousout|onmouseover|onmouseup|onmousewheel|onmove|onmoveend|onmovestart|onabort|onactivate|onafterprint|onafterupdate|onbefore|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onblur|onbounce|oncellchange|onchange|onclick|oncontextmenu|onpaste|onpropertychange|onreadystatechange|onreset|onresize|onresizend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onselect|onselectionchange|onselectstart|onstart|onstop|onsubmit|onunload)+\\s*=+", Pattern.CASE_INSENSITIVE);
            matcher = scriptPattern.matcher(value);
            if (matcher.find() && StrUtil.isNotEmpty(matcher.group())) {
                return matcher.group();
            }
        }
        return null;
    }

}
